package com.znyj.cloud.chain.util;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import org.springframework.util.CollectionUtils;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by gaoliwei on 15-1-14.
 */
public class ByteUtil {

    private final static char[] mChars = "0123456789ABCDEF".toCharArray();

    public static int intTointBIG(int value) {
        int srcint = (((value) & 0xff) << 24) + (((value >> 8) & 0xff) << 16) + (((value >> 16) & 0xff) << 8) + (((value >> 24) & 0xff));
        return srcint;
    }

    public static String assembleBytes2HexStr(ByteBuf buf) {
        StringBuilder builder = new StringBuilder();

        byte[] bytes = buf.array();
        if (bytes.length == 0) {
            return "";
        }

        while (buf.isReadable()) {
            byte b = buf.readByte();
            builder.append(mChars[(b & 0xFF) >> 4]);
            builder.append(mChars[b & 0x0F]);
        }

        return builder.toString();
    }

    public static String byte2String(byte[] bytes) {
        StringBuffer tStringBuf = new StringBuffer();
        char[] tChars = new char[bytes.length];

        for (int i = 0; i < bytes.length; i++)
            tChars[i] = (char) bytes[i];

        tStringBuf.append(tChars);
        return tStringBuf.toString();
    }

    public static String assembleBytes2HexStr(byte[] bytes) {
        StringBuilder builder = new StringBuilder();

        if (bytes.length == 0) {
            return "";
        }

        for (byte b : bytes) {
            builder.append(mChars[(b & 0xFF) >> 4]);
            builder.append(mChars[b & 0x0F]);
        }

        return builder.toString();
    }

    public static List<String> assembleBytes2HexStr(List<ByteBuf> buffers) {
        List<String> hexStrings = new ArrayList<String>();
        for (ByteBuf buf : buffers) {
            String hexStr = assembleBytes2HexStr(buf);
            hexStrings.add(hexStr);
        }
        return hexStrings;
    }

    public static ByteBuf hexString2Buffer(String hexString) throws Exception {
//        if (hexString.length() % 2 == 1) {
//            throw new Exception("bytes_str's length can't be odd");
//        }
//
//        byte[] byteList = new byte[hexString.length() / 2];
//
//        int iTemp = 0x00;
//        for (int i = 0; i < hexString.length(); i += 2) {
//            char c1 = hexString.charAt(i);
//            char c2 = hexString.charAt(i + 1);
//            if (!isCharInHex(c1) || !isCharInHex(c2)) {
//                throw new Exception("bytes_str must be 0~9,a~f,A~F");
//            }
//
//            iTemp = hexChar2Byte(c1) << 4;
//            iTemp |= hexChar2Byte(c2);
//
//            Byte thisByte = new Byte((byte) iTemp);
//            byteList[i/2] = thisByte;
//
//        }
        byte[] byteList = hexString2ByteArray(hexString);
        ByteBuf byteBuf = Unpooled.copiedBuffer(byteList);
        return byteBuf;
    }

    public static byte[] hexString2ByteArray(String hexString) throws Exception {
        if (hexString.length() % 2 == 1) {
            throw new Exception("bytes_str's length can't be odd");
        }

        byte[] byteList = new byte[hexString.length() / 2];

        int iTemp = 0x00;
        for (int i = 0; i < hexString.length(); i += 2) {
            char c1 = hexString.charAt(i);
            char c2 = hexString.charAt(i + 1);
            if (!isCharInHex(c1) || !isCharInHex(c2)) {
                throw new Exception("bytes_str must be 0~9,a~f,A~F");
            }

            iTemp = hexChar2Byte(c1) << 4;
            iTemp |= hexChar2Byte(c2);

            Byte thisByte = new Byte((byte) iTemp);
            byteList[i / 2] = thisByte;

        }
        return byteList;
    }

    public static int hexChar2Byte(char hexChar) {
        if (hexChar > 47 && hexChar < 58) {
            return hexChar - 48;
        }
        if (hexChar > 64 && hexChar < 71) {
            return hexChar - 55;
        }
        if (hexChar > 96 && hexChar < 103) {
            return hexChar - 87;
        }
        return 0;

    }

    public static boolean isCharInHex(char c) {
        if (c > 47 && c < 58) {
            return true;
        }
        if (c > 64 && c < 71) {
            return true;
        }
        if (c > 96 && c < 103) {
            return true;
        }
        return false;
    }

    public static void main(String[] args) {
        List<Character> chars = new ArrayList<Character>();
        chars.add('0');
        chars.add('9');
        chars.add('5');
        chars.add('A');
        chars.add('F');
        chars.add('B');
        chars.add('a');
        chars.add('f');
        chars.add('b');
        chars.add('g');
        chars.add(',');
        for (Character c : chars) {
            System.out.println(c + "  " + isCharInHex(c));
        }
    }

    public static String readStringFromByteBuf(ByteBuf buf, int length) throws UnsupportedEncodingException {

        byte[] bytes = new byte[length];
        for (int i = 0; i < length; i++) {
            bytes[i] = buf.readByte();
        }

        return new String(bytes, "UTF-8");
    }

    public static void writeString2ByteBuf(ByteBuf buf, String content, int length) throws Exception {
        byte[] str = content.getBytes("UTF-8");
        if (str.length > length) {
            throw new Exception("string be write size is big than length ");
        }

        for (byte c : str) {
            buf.writeByte(c);
        }

        for (int i = str.length; i < length; i++) {
            buf.writeByte(0);
        }

    }

    /**
     * 释放buffer
     *
     * @param buffers
     */
    public static void releaseBuffers(List<ByteBuf> buffers) {

        if (CollectionUtils.isEmpty(buffers)) {
            return;
        }

        for (ByteBuf buf : buffers) {
            buf.release();
        }
    }

    public static String showLongAsHex(long num) {
        return Long.toHexString(num);
    }


    public static void printHexBytesArray(String hint, byte[] b) {
        System.out.print(hint);
        for (int i = 0; i < b.length; i++) {
            String hex = Integer.toHexString(b[i] & 0xFF);
            if (hex.length() == 1) {
                hex = "0x0" + hex;
            }
            System.out.print(hex.toUpperCase() + " ");
        }
        System.out.println("");
    }

}
